﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Security.Controller;
using Pixysoft.Security;
using System.Web;
using Pixysoft.Framework.Security.Tokens;
using Pixysoft.Framework.Security.Core;
using Pixysoft.Framework.Security.Entity;
using System.IO;

namespace Pixysoft.Framework.Security
{
    public class SSoManager
    {
        private static volatile SSoManager instance;

        private static object syncRoot = new Object();

        public static SSoManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            instance = new SSoManager();
                        }
                    }
                }
                return instance;
            }
        }

        public static void Initialize(SecurityConfiguration config)
        {
            SettingHelper.Initialize(config);
        }


        public string TokenLogin(string username, string md5password)
        {
            return TokenLogin(username, md5password, TokenHelper.default_tokendb_TimeOut);
        }

        public string TokenLogin(string username, string md5password, int timeoutMins)
        {
            return SSoTokenController.Instance.TokenLogin(username, md5password, timeoutMins);
        }

        public void TokenLogout(string token)
        {
            SSoTokenController.Instance.TokenLogout(token);
        }

        public bool TokenValidate(string token)
        {
            return SSoTokenController.Instance.TokenValidate(token);
        }

        public bool TokenValidate(string token, string accessname)
        {
            return SSoTokenController.Instance.TokenValidate(token, accessname);
        }

        public bool TokenExtend(string token)
        {
            return SSoTokenController.Instance.TokenExtend(token);
        }



        /// <summary>
        /// 取得自动登录信息
        /// </summary>
        /// <returns></returns>
        public AutoLoginInfo GetAutoLoginInfo()
        {
            return WebSecurityManager.Instance.GetAutoLoginInfo();
        }

        /// <summary>
        /// 设置自动登录
        /// </summary>
        /// <returns></returns>
        public AutoLoginInfo SetAutoLoginInfo(string username, string password, bool autologin)
        {
            return WebSecurityManager.Instance.SetAutoLoginInfo(username, password, autologin);
        }

        /// <summary>
        /// 尝试自动登录
        /// </summary>
        /// <returns></returns>
        public SecurityResult AutoLogin()
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.AutoLogin();

            return AutoLogin(null);
        }

        /// <summary>
        /// 尝试自动登录
        /// </summary>
        /// <returns></returns>
        public SecurityResult AutoLogin(LoginCallback logincallback)
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.AutoLogin(logincallback);

            AutoLoginInfo info = WebAuthController.GetAutoLoginInfo();

            if (info == null)
                return SecurityResult.NoUser;

            if (!info.IsAutoLogin)
                return SecurityResult.NoUser;

            string userName = info.Username;

            string md5password = info.Md5Password;

            PrivateLogoutNoRedirect();

            return PrivateLogin(userName, md5password, logincallback);
        }

        /// <summary>
        /// 匿名登录
        /// </summary>
        /// <returns></returns>
        public bool AnonymousLogin()
        {
            return WebSecurityManager.Instance.AnonymousLogin();
        }

        /// <summary>
        /// 登录失败，则保持原地址
        /// 登录成功，如果有返回地址则返回，没有就返回默认页面
        /// -2:用户锁定;-1:用户不存在;0密码错误;1:登录成功
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="pwd">The PWD.</param>
        /// <returns></returns>
        public SecurityResult Login(string userName, string pwd)
        {
            return Login(userName, pwd, null);
        }

        /// <summary>
        /// 登录失败，则保持原地址
        /// 登录成功，如果有返回地址则返回，没有就返回默认页面
        /// -2:用户锁定;-1:用户不存在;0密码错误;1:登录成功
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="pwd">The PWD.</param>
        /// <returns></returns>
        public SecurityResult Login(string userName, string pwd, LoginCallback logincallback)
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.Login(userName, pwd, logincallback);


            //登出 删除usrprofile信息

            PrivateLogoutNoRedirect();



            //输入验证

            if (userName == null || userName.Trim() == "")
                return SecurityResult.NoUser;

            if (pwd == null || pwd.Trim() == "")
                return SecurityResult.NoPwd;

            userName = userName.Trim().ToUpper();

            pwd = pwd.Trim();

            pwd = MD5.GetMD5(pwd);


            return PrivateLogin(userName, pwd, logincallback);
        }

        /// <summary>
        /// 内部登录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="md5password"></param>
        /// <returns></returns>
        internal SecurityResult PrivateLogin(string userName, string md5password, LoginCallback logincallback)
        {
            //取得用户 验证密码

            ISSoLoginResponse respnose = new SSoConnection(SettingHelper.Instance.SSoUrl).Login(userName, md5password);

            if (respnose.Result != SecurityResult.Succeed)
                return respnose.Result;


            //初始化session

            Pixysoft.Web.SessionHelper.Instance.ClearSession();




            //在缓存创建用户信息usrprofile

            string token = StringHelper.GetToken();

            UserInfo profile = respnose.UserInfo;

            profile.Token = token;

            WebAuthController.AddProfile(profile);

            Pixysoft.Web.CookieHelper.Instance.AddCookie(HttpContext.Current, StringHelper.cookieName_userinfo, token);


            //添加了回调函数

            if (logincallback != null)
                logincallback(userName);

            string url = GetLoginRedirectUrl();

            LoggerHelper.Debug("redirect url = " + url);

            HttpContext.Current.Response.Redirect(url, true);

            return SecurityResult.Succeed;
        }


        /// <summary>
        /// 自动登录
        /// </summary>
        /// <returns></returns>
        public SecurityResult AutoLoginNoRedirect()
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.AutoLoginNoRedirect();

            AutoLoginInfo info = WebAuthController.GetAutoLoginInfo();

            if (info == null)
                return SecurityResult.NoUser;

            if (!info.IsAutoLogin)
                return SecurityResult.NoUser;

            return AutoLoginNoRedirect(info);
        }

        /// <summary>
        /// 自动登录
        /// </summary>
        /// <returns></returns>
        public SecurityResult AutoLoginNoRedirect(AutoLoginInfo info)
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.AutoLoginNoRedirect(info);

            if (info == null)
                return SecurityResult.NoUser;

            string userName = info.Username;

            string md5password = info.Md5Password;

            PrivateLogoutNoRedirect();

            return PrivateLoginNoRedirect(userName, md5password);
        }

        /// <summary>
        /// 不跳转登录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public SecurityResult LoginNoRedirect(string userName, string pwd)
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.LoginNoRedirect(userName, pwd);

            //登出 删除usrprofile信息

            PrivateLogoutNoRedirect();



            //输入验证

            if (userName == null || userName.Trim() == "")
                return SecurityResult.NoUser;

            if (pwd == null || pwd.Trim() == "")
                return SecurityResult.NoPwd;

            userName = userName.Trim().ToUpper();

            pwd = pwd.Trim();

            pwd = MD5.GetMD5(pwd);



            SecurityResult result = PrivateLoginNoRedirect(userName, pwd);

            return result;
        }

        /// <summary>
        /// 获取登录跳转的URL
        /// </summary>
        /// <returns></returns>
        public string GetLoginRedirectUrl()
        {
            return WebSecurityManager.Instance.GetLoginRedirectUrl();
        }

        /// <summary>
        /// 获取登录跳转的URL
        /// </summary>
        /// <returns></returns>
        public string GetLoginRedirectUrl(string url)
        {
            return WebSecurityManager.Instance.GetLoginRedirectUrl(url);
        }

        /// <summary>
        /// 内部登录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="md5password"></param>
        /// <returns></returns>
        internal SecurityResult PrivateLoginNoRedirect(string userName, string md5password)
        {
            //取得用户 验证密码

            ISSoLoginResponse respnose = new SSoConnection(SettingHelper.Instance.SSoUrl).Login(userName, md5password);

            if (respnose.Result != SecurityResult.Succeed)
                return respnose.Result;


            //初始化session

            Pixysoft.Web.SessionHelper.Instance.ClearSession();




            //在缓存创建用户信息usrprofile

            string token = StringHelper.GetToken();

            UserInfo profile = respnose.UserInfo;

            profile.Token = token;

            profile.IsAnonymous = false;

            WebAuthController.AddProfile(profile);

            Pixysoft.Web.CookieHelper.Instance.AddCookie(HttpContext.Current, StringHelper.cookieName_userinfo, token);


            return SecurityResult.Succeed;
        }



        /// <summary>
        /// 取消自动登录
        /// 如果没有登录，则进入登录页面
        /// 如果登录了，则返回登录页面
        /// </summary>
        public void Logout()
        {
            WebSecurityManager.Instance.Logout();
        }

        /// <summary>
        /// 取消自动登录
        /// 如果登录了就登出 否则返回
        /// </summary>
        public void LogoutNoRedirect()
        {
            WebSecurityManager.Instance.LogoutNoRedirect();
        }

        internal void PrivateLogoutNoRedirect()
        {
            WebSecurityManager.Instance.PrivateLogoutNoRedirect();
        }



        /// <summary>
        /// Determines whether this instance is logined.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if this instance is logined; otherwise, <c>false</c>.
        /// </returns>
        public bool IsLogined()
        {
            return WebSecurityManager.Instance.IsLogined();
        }

        /// <summary>
        /// 检查此用户是否登录
        /// </summary>
        /// <param name="loginName"></param>
        /// <returns></returns>
        public bool IsLogined(string loginName)
        {
            return WebSecurityManager.Instance.IsLogined();
        }

        /// <summary>
        /// 页面是否允许访问 使用内存数据判断 即使是sso，一旦登录了本地一样缓存了userinfo，所以仍然是内存判断
        /// </summary>
        /// <param name="pageAuthName"></param>
        /// <returns></returns>
        public bool IsPagePermitted(string pageAuthName)
        {
            return WebSecurityManager.Instance.IsPagePermitted(pageAuthName);
        }

        /// <summary>
        /// 是否匿名登录
        /// </summary>
        /// <returns></returns>
        public bool IsAnonymous()
        {
            return WebSecurityManager.Instance.IsAnonymous();
        }


        /// <summary>
        /// 取得登录的用户名,没有就登录
        /// </summary>
        /// <returns></returns>
        public string GetLoginUserName()
        {
            UserInfo profile = WebAuthController.GetUserInfo();

            if (profile == null)
            {
                RedirectToLogin();

                return null;
            }

            return profile.Name;
        }

        /// <summary>
        /// 取得用户登录信息,没有就登录
        /// </summary>
        /// <returns></returns>
        public UserInfo GetLoginUserInfo()
        {
            UserInfo profile = WebAuthController.GetUserInfo();

            if (profile == null)
            {
                RedirectToLogin();

                return null;
            }

            return profile;
        }

        /// <summary>
        /// 跳转到登录页面
        /// </summary>
        public void RedirectToLogin()
        {
            RedirectToLogin(false);
        }

        public void RedirectToLogin(bool redirectBack)
        {
            if (SettingHelper.Instance.SSoDisabled)
            {
                WebSecurityManager.Instance.RedirectToLogin(redirectBack);
                return;
            }

            if (!redirectBack)
            {
                WebSecurityManager.Instance.RedirectToLogin(redirectBack);
                return;
            }

            HttpContext app = HttpContext.Current;

            string url = Pixysoft.Security.DES.Encrypt(app.Request.Url.AbsoluteUri, StringHelper.desKey);

            LoggerHelper.Debug("redirect to ssologin, sso.redirect = " + url);

            url = Pixysoft.Security.UrlCoder.UrlEncode(url);

            string ssourl = Pixysoft.Web.UrlHelper.Instance.MakeUrlDirective(SettingHelper.Instance.SSoResponseUrl, app.Request);

            LoggerHelper.Debug("redirect to ssologin, sso.ssoresponse = " + ssourl);

            ssourl = Pixysoft.Security.DES.Encrypt(ssourl, StringHelper.desKey);

            ssourl = Pixysoft.Security.UrlCoder.UrlEncode(ssourl);

            Dictionary<string, string> list = new Dictionary<string, string>();

            list.Add(StringHelper.querystring_redirectName, url);

            list.Add(StringHelper.querystring_ssoName, ssourl);

            list.Add(StringHelper.querystring_commandName, SSoCommandCollection.SSoLoginRequest);

            LoggerHelper.Debug("redirect to ssologin, sso.ssorequest = " + SettingHelper.Instance.SSoUrl);

            app.Response.Redirect(Pixysoft.Web.UrlHelper.Instance.CombineUrl(SettingHelper.Instance.SSoUrl, list), true);
        }

        /// <summary>
        /// 登陆前转移 用于登陆后自动跳转到登陆前页面
        /// </summary>
        public void RedirectBeforeLogin()
        {
            WebSecurityManager.Instance.RedirectBeforeLogin();
        }



        /// <summary>
        /// 忽略动作查询资源权限
        /// </summary>
        /// <param name="user"></param>
        /// <param name="operType"></param>
        /// <param name="resName"></param>
        /// <returns></returns>
        public bool IsPermitted(string username, string md5password, string resourceName)
        {
            if (SettingHelper.Instance.SSoDisabled)
                return WebSecurityManager.Instance.IsPermitted(username, md5password, resourceName);

            return new SSoConnection(SettingHelper.Instance.SSoUrl).IsPermitted(username, md5password, resourceName);
        }
    }
}
